package com.windaka.elements.config;


import com.windaka.elements.service.JdbcUserDetailsServiceImpl;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;


/**
 * 认证管理
 * 配置了:
 * client怎么认证
 * 认证器
 * token存储
 * token时效
 * 用户如何认证等...
 * @author song
 * @date 3:04 下午 2021/11/9
 * @param 
 * @return 
 * @other
**/
@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private DataSource dataSource;

    @Resource
    private TokenStore tokenStore;

    @Resource
    private DefaultTokenServices tokenServices;

    @Resource
    private JdbcUserDetailsServiceImpl jdbcUserDetailsServiceImpl;

    /**
     * 配置 AuthorizationServerEndpointsConfigurer
     * @author song
     * @date 2:17 下午 2021/11/16
     * @param 
     * @return 
     * @other
    **/
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // 配置
        endpoints
                // 配置认证管理器
                // 认证管理器是默认的 这里自动注入就好
                // bean在WebSecurityConfig中的AuthenticationManager配置了
                .authenticationManager(authenticationManager)
                // 配置token存储的 服务 与 位置
                // Bean在TokenStoreConfig中
                // 修改成了redis存储 并且access_token也修改成了UUID
                .tokenStore(tokenStore)
                // 配置token存储的 服务 与 位置
                // Bean在TokenServiceConfig中
                // 配置了一些token过期时间之类的 (如果不配置 从oauth_client_details表中配置也可以)
                .tokenServices(tokenServices)
                // 配置用户服务
                // Bean在JdbcUserDetailsServiceImpl中
                // 用于用户输入的账号密码进行校验 认证逻辑 以及权限的查询、组装
                // 区别于 JdbcClientDetailsService 不要看花眼了
                // jdbcUserDetailsServiceImpl是用于校验账号密码的
                // JdbcClientDetailsService是从oauth_client_details表中读取信息的
                .userDetailsService(jdbcUserDetailsServiceImpl);
    }
    
    /**
     * 配置 ClientDetailsServiceConfigurer
     * @author song
     * @date 2:18 下午 2021/11/16
     * @param 
     * @return 
     * @other
    **/
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 认证的时候 选择的是 从数据库里查询
        // 认证的时候 需要填写:
        // grant_type: password
        // client_id: app
        // client_secret: 111111
        // 这些信息是存到 数据库中的 oauth_client_details 的
        clients.withClientDetails(new JdbcClientDetailsService(dataSource));
    }

    /**
     * 配置 AuthorizationServerSecurityConfigurer
     * @author song
     * @date 2:18 下午 2021/11/16
     * @param
     * @return
     * @other
     **/
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        // 允许 表单认证的形式
        // 这里必须要配置 允许表单形式
        // 开启该项 会 放开 /oauth/token 这个接口
        // 如果不配置 则会出现 /oauth/token 被拦截掉 无法进行认证
        security.allowFormAuthenticationForClients();
    }

}
